/* Copyright (c) 2021 Qualcomm Technologies International, Ltd. */
/* %%version */

#include "gatt_cas_server_common.h"
#include "gatt_cas_server_debug.h"
#include "gatt_cas_server_db.h"

#define GATT_CAS_SERVER_INVALID_CID_INDEX  (0xFF)

static status_t casServerSetCCC(GCAS *common_audio_server,
                            connection_id_t cid,
                            uint16 handle,
                            uint8 *ccc)
{
    UNUSED(handle);
    UNUSED(ccc);

    uint8 index_client = casServerGetCidIndex(common_audio_server, cid);

    if(index_client != GATT_CAS_SERVER_INVALID_CID_INDEX)
    {
        {
            /* Invalid handle */
            GATT_CAS_SERVER_ERROR("Invalid handle!\n");
            return CSR_BT_GATT_RESULT_INVALID_HANDLE_RANGE;
        }
    }
    else
    {
        /* Invalid cid */
        GATT_CAS_SERVER_ERROR("Invalid cid!\n");
        return CSR_BT_GATT_RESULT_UNKNOWN_CONN_ID;
    }

    /* Never CSR_BT_GATT_RESULT_SUCCESS as there are no characteristics that support this */
}

/******************************************************************************/
void casServerSendAccessRsp(
        CsrBtGattId task,
        uint16 cid,
        uint16 handle,
        uint16 result,
        uint16 size_value,
        uint8 *const value
        )
{
    CsrBtGattDbReadAccessResSend(
                task,
                cid,
                handle,
                result,
                size_value,
                value
                );

}

/******************************************************************************/
void casServerWriteGenericResponse(
        CsrBtGattId        task,
        uint16      cid,
        uint16      result,
        uint16      handle
        )
{
    if (task == CSR_BT_GATT_INVALID_GATT_ID)
    {
        GATT_CAS_SERVER_PANIC(
                    "GCAS: Invalid GattId!\n"
                    );
    }
    else if (cid == 0)
    {
        GATT_CAS_SERVER_PANIC(
                    "GCAS: No Cid!\n"
                    );
    }
    else
    {
        CsrBtGattDbWriteAccessResSend(
             task,
             cid,
             handle,
             (CsrBtGattDbAccessRspCode)result);
    }
}

/***************************************************************************/
void casServerSendCharacteristicChangedNotification(
        CsrBtGattId task,
        connection_id_t cid,
        uint16 handle,
        uint16 size_value,
        uint8 *const value
        )
{
    if (task == CSR_BT_GATT_INVALID_GATT_ID)
    {
        GATT_CAS_SERVER_PANIC(
                    "GCAS: Null instance!\n"
                    );
    }
    else if ( cid == 0 )
    {
        GATT_CAS_SERVER_PANIC(
                    "GCAS: No Cid!\n"
                    );
    }
    else
    {
        CsrBtGattNotificationEventReqSend(
                                      task,
                                      cid,
                                      handle,
                                      size_value,
                                      value);
    }
}

/***************************************************************************/
void casServerHandleReadClientConfigAccess(
        CsrBtGattId task,
        uint16 cid,
        uint16 handle,
        const uint16 client_config
        )
{
    uint8 config_data[GATT_CAS_SERVER_CCC_VALUE_SIZE];

    if (task == CSR_BT_GATT_INVALID_GATT_ID)
    {
        GATT_CAS_SERVER_PANIC(
                    "GCAS: Invalid GattID\n"
                    );
    }
    else if (cid == 0)
    {
        GATT_CAS_SERVER_PANIC(
                    "GCAS: Null instance!\n"
                    );
    }

    config_data[0] = (uint8)client_config & 0xFF;
    config_data[1] = (uint8)client_config >> 8;

    casServerSendAccessRsp(
            task,
            cid,
            handle,
            CSR_BT_GATT_RESULT_SUCCESS,
            GATT_CAS_SERVER_CCC_VALUE_SIZE,
            config_data
            );
}

/***************************************************************************/
void casServerHandleWriteClientConfigAccess(
        GCAS *common_audio_server,
        const GATT_MANAGER_SERVER_ACCESS_IND_T *access_ind)
{
    if (access_ind->size_value != GATT_CAS_SERVER_CCC_VALUE_SIZE)
    {
        casServerSendAccessErrorRsp(
                common_audio_server->gattId,
                access_ind->cid,
                access_ind->handle,
                CSR_BT_GATT_RESULT_INVALID_LENGTH
                );
    }
    /* Validate the input parameters - ONLY Notify*/
    else if (access_ind->value[0] == GATT_CAS_SERVER_CCC_INDICATE)
    {
        casServerSendAccessErrorRsp(
                common_audio_server->gattId,
                access_ind->cid,
                access_ind->handle,
                CSR_BT_GATT_RESULT_UNACCEPTABLE_PARAMETER
                );
    }
    else if (access_ind->value[0] == GATT_CAS_SERVER_CCC_NOTIFY || access_ind->value[0] == 0)
    {
        /* Save the new ccc in the library */
        status_t status = casServerSetCCC( common_audio_server,
                                                (connection_id_t) access_ind->cid,
                                                access_ind->handle,
                                                access_ind->value);

        /* Send response to the client */
        casServerWriteGenericResponse(
                    common_audio_server->gattId,
                    access_ind->cid,
                    status,
                    access_ind->handle
                    );
    }
    else
    {
        /* Send response to the client but the value is ignored*/
        casServerWriteGenericResponse(
                    common_audio_server->gattId,
                    access_ind->cid,
                    CSR_BT_GATT_RESULT_SUCCESS,
                    access_ind->handle
                    );
    }
}


/******************************************************************************/
uint8 casServerGetCidIndex(GCAS *common_audio_server, connection_id_t cid)
{
    uint8 index = GATT_CAS_SERVER_INVALID_CID_INDEX;
    uint8 i;

    for (i=0; i<GATT_CAS_MAX_CONNECTIONS; i++)
    {
        if(common_audio_server->data.connected_clients[i].cid == cid)
        {
            index = i;
            break;
        }
    }

    return index;
}
